package com.frejoys.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.frejoys.api.service.ApiAppService;
import com.frejoys.common.config.ValueConfig;
import com.frejoys.common.config.WxMaConfiguration;
import com.frejoys.common.dto.admin.SubmitVerifyDto;
import com.frejoys.common.enums.*;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.CacheKeyUtil;
import com.frejoys.common.util.CommonUtil;
import com.frejoys.common.util.RedisUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.app.UserExtendVerifyVo;
import com.frejoys.common.vo.common.WxH5UserInfoVo;
import com.frejoys.common.vo.common.WxH5Vo;
import com.frejoys.dao.entity.*;
import com.frejoys.dao.mapper.*;
import com.frejoys.service.CommonService;
import com.frejoys.service.PlatformService;
import com.frejoys.service.UserCodeService;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;

// 公共service
@Service
@RequiredArgsConstructor
public class CommonServiceImpl implements CommonService {

    private final ValueConfig valueConfig;

    private final RedisUtil redisUtil;

    private final UserMapper userMapper;

    private final UserLevelPromotionMapper userLevelPromotionMapper;

    private final UserLevelAgentMapper userLevelAgentMapper;

    private final StoreMapper storeMapper;

    private final GoodsMapper goodsMapper;

    private final StoreActivityMapper storeActivityMapper;

    private final StoreEnterMapper storeEnterMapper;

    private final PlatformService platformService;

    private final ApiAppService apiAppService;

    private final UserCodeMapper userCodeMapper;

    private final UserCodeService userCodeService;



    @Override
    public String getWxAccessToken(Integer site) {
        String key = CacheKeyUtil.accessTokenCacheKey(site);
        Object obj = redisUtil.get(key);
        if (obj != null) {
            return obj.toString();
        }

        WxMaService wxService;

        if (site.equals(ESite.app.getValue())) {
            wxService = WxMaConfiguration.getMaService(valueConfig.getAppAppid());
        } else if (site.equals(ESite.store.getValue())) {
            wxService = WxMaConfiguration.getMaService(valueConfig.getStoreAppid());
        } else {
            return "";
        }

        String accessToken = "";

        try {
            // 每次都刷新
            accessToken = wxService.getAccessToken(true);
            if (StrUtil.isNotEmpty(accessToken)) {
                // 放入缓存
                redisUtil.set(key, accessToken, 7000L);
            }
        } catch (WxErrorException e) {
            e.printStackTrace();
        }

        return accessToken;
    }

    /**
     * 微信H5登录
     *
     * @param code
     * @param site
     */
    @Override
    public WxH5Vo getWxH5AccessToken(String code, Integer site) {


        if (redisUtil.hasKey(CacheKeyUtil.accessTokenH5CacheKey(site))) {
            String json = (String) redisUtil.get(CacheKeyUtil.accessTokenH5CacheKey(site));
            JSONObject object = JSONUtil.parseObj(json);
            return JSONUtil.toBean(object, WxH5Vo.class);
        }

        String appid = null;
        String secret = null;

        if (site.equals(ESite.app.getValue())) {
            appid = valueConfig.getAppAppid();
            secret = valueConfig.getAppAppSecret();
        } else if (site.equals(ESite.store.getValue())) {
            appid = valueConfig.getStoreAppid();
            secret = valueConfig.getStoreAppSecret();
        } else {
            appid = valueConfig.getOfficialAppid();
            secret = valueConfig.getOfficialAppSecret();
        }
        if (appid == null && secret == null) {
            throw new GeneralException(HttpStatus.systemError);
        }

        WxH5Vo h5Vo = apiAppService.getH5WxAccessToken(appid, secret, code);

        if (ObjectUtil.isNotEmpty(h5Vo)) {
            if (!redisUtil.set(CacheKeyUtil.accessTokenH5CacheKey(site), JSONUtil.toJsonStr(h5Vo), 7000L)) {
                throw new GeneralException(HttpStatus.systemError);
            }
        }
        return h5Vo;

    }

    /**
     * 验证accessToken是否有效
     *
     * @param accessToken
     * @param openid
     */
    @Override
    public boolean validateAccessToken(String accessToken, String openid) {
        return apiAppService.validateAccessToken(accessToken, openid);
    }

    /**
     * 刷新H5 access_token
     *
     * @param refreshToken
     * @param site
     */
    @Override
    public WxH5Vo H5WxRefreshToken(String refreshToken, Integer site) {
        String appid = null;

        if (site.equals(ESite.app.getValue())) {
            appid = valueConfig.getAppAppid();
        } else if (site.equals(ESite.store.getValue())) {
            appid = valueConfig.getStoreAppid();
        } else {
            appid = valueConfig.getOfficialAppid();
        }
        if (appid == null) {
            throw new GeneralException(HttpStatus.systemError);
        }
        WxH5Vo h5Vo = apiAppService.h5WxRefreshToken(appid, refreshToken);
        if (ObjectUtil.isNotEmpty(h5Vo)) {
            if (!redisUtil.set(CacheKeyUtil.accessTokenH5CacheKey(site), JSONUtil.toJsonStr(h5Vo), 7000L)) {
                throw new GeneralException(HttpStatus.systemError);
            }
        }
        return h5Vo;
    }

    /**
     * h5登录获取用户信息（除手机号）
     *
     * @param accessToken
     * @param openid
     * @return
     */
    @Override
    public WxH5UserInfoVo h5GetUserInfo(String accessToken, String openid) {
        return apiAppService.h5GetUserInfo(accessToken, openid);
    }

    @Override
    public void delWxAccessToken(Integer site) {
        redisUtil.del(CacheKeyUtil.accessTokenCacheKey(site));
    }

    /**
     * 用户推广
     *
     * @param user   推广者
     * @param userId 被推广用户id
     * @return
     */
    // @Override
    // @Transactional(rollbackFor = Exception.class)
    // public boolean userExtend(User user, Long userId) {
    //     //验证推广
    //     verifyIdentify(user, userMapper.getSimpleUser(userId));
    //     Integer role = 0;
    //
    //
    //     //用户是代理
    //     if (CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue())) {
    //         role = EUserRole.agent.getValue();
    //     } else if (CommonUtil.bitExistOffset(user.getRole(),EUserRole.promotion.getValue())){
    //         //用户是达人
    //         role = EUserRole.promotion.getValue();
    //     }
    //
    //     LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate();
    //     wrapper.set(User::getRole, role).eq(User::getId, userId);
    //     //更新被推广用户
    //     userMapper.update(wrapper);
    //
    //     //添加代理人邀请码
    //     LambdaQueryWrapper<UserCode> queryWrapper = new LambdaQueryWrapper<>();
    //     queryWrapper.select(UserCode::getCode);
    //     List<UserCode> userCodes = userCodeMapper.selectList(queryWrapper);
    //     List<String> codes = userCodes.stream().map(UserCode::getCode).toList();
    //
    //     String code = null;
    //     //生成邀请码
    //     for (int i = 0;i < 10; i++) {
    //         code = CommonUtil.getAgentCode(codes);
    //         if (code != null){
    //             break;
    //         }
    //     }
    //     if (code == null){
    //         throw new GeneralException(HttpStatus.notCodeError);
    //     }
    //
    //     UserCode userCode = new UserCode();
    //     userCode.setCode(code);
    //     userCode.setUserId(userId);
    //     userCodeMapper.insert(userCode);
    //
    //     //插入达人推广表
    //     if (user.getRole().equals(EUserRole.promotion.getValue())) {
    //         //查询推广者父级
    //         Long parentId = userLevelPromotionMapper.getParentId(user.getId());
    //         UserLevelPromotion userLevelPromotion = new UserLevelPromotion();
    //         userLevelPromotion.setUserId(user.getId());
    //         userLevelPromotion.setChildUserId(userId);
    //         userLevelPromotion.setParentUserId(ObjectUtils.isEmpty(parentId) ? 0 : parentId);
    //         userLevelPromotion.setCreateTime(TimeUtil.unixTime());
    //         userLevelPromotionMapper.insert(userLevelPromotion);
    //
    //     }
    //
    //     //插入达人代理商推广表
    //     if (CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue())) {
    //         //查询推广者父级
    //         Long parentId = userLevelAgentMapper.getParentId(user.getId());
    //         UserLevelAgent userLevelAgent = new UserLevelAgent();
    //         userLevelAgent.setUserId(user.getId());
    //         userLevelAgent.setChildUserId(userId);
    //         userLevelAgent.setParentUserId(ObjectUtils.isEmpty(parentId) ? 0 : parentId);
    //         userLevelAgent.setCreateTime(TimeUtil.unixTime());
    //         userLevelAgentMapper.insert(userLevelAgent);
    //
    //     }
    //     return true;
    //
    // }


    /**
     * 验证推广者身份
     *
     * @param user          推广者
     * @param promotionUser 被推广者
     */
    // @Override
    // public UserExtendVerifyVo verifyIdentify(User user, User promotionUser) {
    //     //判断推广用户是否存在
    //     if (ObjectUtils.isEmpty(user)) {
    //         throw new GeneralException(HttpStatus.extendUserNoExist);
    //     }
    //     //推广人被禁止登录
    //     if (!user.getStatus().equals(EStatus.on.getValue())) {
    //         throw new GeneralException(HttpStatus.extendUserLoginError);
    //     }
    //     //判断被推广者是否被禁止
    //     if (!promotionUser.getStatus().equals(EStatus.on.getValue())) {
    //         throw new GeneralException(HttpStatus.userStatusLoginError);
    //     }
    //     //用户是达人
    //     if (CommonUtil.bitExistOffset(promotionUser.getRole(),EUserRole.promotion.getValue())){
    //         throw new GeneralException(HttpStatus.userPromotionExistExist);
    //     }
    //     //用户已经是代理
    //     if (CommonUtil.bitExistOffset(promotionUser.getRole(), EUserRole.agent.getValue())) {
    //         throw new GeneralException(HttpStatus.userIsAgentExist);
    //     }
    //     //用户已经是商家
    //     if (CommonUtil.bitExistOffset(promotionUser.getRole(), EUserRole.store.getValue())) {
    //         throw new GeneralException(HttpStatus.userIsAgentExist);
    //     }
    //     //推荐人不是代理人并且不是达人
    //     if (!CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue()) && !CommonUtil.bitExistOffset(user.getRole(), EUserRole.promotion.getValue())) {
    //         throw new GeneralException(HttpStatus.extendUserError);
    //     }
    //     UserExtendVerifyVo vo = new UserExtendVerifyVo();
    //     vo.setNickname(user.getNickname());
    //     vo.setRole(user.getRole());
    //     vo.setIsScan(true);
    //     return vo;
    // }


    @Override
    public boolean offShelve(SubmitVerifyDto dto) {
        Integer shelves = EShelves.offShelf.getValue();
        // 处于申请状态时不允许下架
        if (dto.getType().equals(EAdminVerifyType.store.getValue())) {
            Store store = storeMapper.getShelvesInfo(dto.getCommonId());

            if (store == null) {
                throw new GeneralException(HttpStatus.storeNotFound);
            }
            if (store.getShelves().equals(EShelves.applyfor.getValue())) {
                throw new GeneralException(HttpStatus.applyPendingError);
            }
            if (store.getShelves() == EShelves.offShelf.getValue()) {
                throw new GeneralException(HttpStatus.soldOutApplyError);
            }

//            //查询该店铺是否存在未下架的商品
//            if (goodsMapper.exists(Wrappers.<Goods>lambdaQuery().eq(Goods::getStoreId, dto.getCommonId())
//                    .eq(Goods::getStatus, EStatus.on.getValue())
//                    .ne(Goods::getShelves, EShelves.offShelf.getValue()))) {
//                throw new GeneralException(HttpStatus.storeHasGoodsOnSale);
//            }
//
//            //查询店铺是否存在正在进行的活动
//            if (storeActivityMapper.exists(Wrappers.<StoreActivity>lambdaQuery().eq(StoreActivity::getStoreId, dto.getCommonId())
//                    .eq(StoreActivity::getStatus, EStatus.on.getValue())
//                    .ne(StoreActivity::getShelves, EShelves.offShelf.getValue()))) {
//                throw new GeneralException(HttpStatus.storeHasActivityOnSale);
//            }
            storeMapper.upShelvesInfo(dto.getCommonId(), shelves);

            LambdaUpdateWrapper<Goods> wrapper = new LambdaUpdateWrapper<>();
            wrapper.set(Goods::getStoreShelves,shelves)
                    .eq(Goods::getStoreId,dto.getCommonId());
            goodsMapper.update(wrapper);
            return true;

        } else if (dto.getType().equals(EAdminVerifyType.goods.getValue())) {

            Goods goods = goodsMapper.getShelvesInfo(dto.getCommonId());

            if (goods == null) {
                throw new GeneralException(HttpStatus.goodsNotFound);
            }
            if (goods.getShelves() == EShelves.offShelf.getValue()) {
                throw new GeneralException(HttpStatus.soldOutApplyError);
            }
            if (goods.getShelves().equals(EShelves.applyfor.getValue())) {
                throw new GeneralException(HttpStatus.applyPendingError);
            }
            //校验店铺商品数量
            int count = goodsMapper.validGoodsCount(goods.getStoreId(), EShelves.onSale.getValue(), EStatus.on.getValue());
            Store store = storeMapper.getShelvesInfo(goods.getStoreId());

            if (count <= 1 && ObjectUtil.isNotEmpty(store) && store.getShelves() != EShelves.offShelf.getValue()){
                throw new GeneralException(HttpStatus.soldOutOrderError);
            }

            return goodsMapper.upShelvesInfo(dto.getCommonId(), shelves);
        } else if (dto.getType().equals(EAdminVerifyType.activity.getValue())) {
            StoreActivity activity = storeActivityMapper.getShelvesInfo(dto.getCommonId());
            if (activity == null) {
                throw new GeneralException(HttpStatus.activityNotFound);
            }
            if (activity.getShelves() == EShelves.offShelf.getValue()) {
                throw new GeneralException(HttpStatus.soldOutApplyError);
            }

            if (activity.getShelves().equals(EShelves.applyfor.getValue())) {
                throw new GeneralException(HttpStatus.applyPendingError);
            }

            int count = storeActivityMapper.getStoreActivity(activity.getStoreId(), activity.getStartTime(),activity.getEndTime());
            Store store = storeMapper.getShelvesInfo(activity.getStoreId());

            if (count <= 1 && ObjectUtil.isNotEmpty(store) && store.getShelves() == EShelves.onSale.getValue()){
                throw new GeneralException(HttpStatus.soldOutStoreActivityError);
            }

            return storeActivityMapper.upShelvesInfo(dto.getCommonId(), shelves);
        }
        throw new GeneralException(HttpStatus.argumentNotValid);
    }

    @Override
    public void limitationMoney(BigDecimal money) {
        Platform platform = platformService.getInfo();
        if (platform.getCashMoney().compareTo(money) > 0) {
            throw new GeneralException(HttpStatus.cashMoneyError);
        }
    }

    public double calculateDistance(double lat1, double lng1, double lat2, double lng2) {
        // 将经纬度转换为弧度
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lng2 - lng1);

        // 使用 Haversine 公式计算距离
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        // 地球半径，6371公里
        return 6371 * c;
    }


}